/*
 *  i2c.c - a device driver for the iic-bus interface 
 *
 *  Copyright (C) 2011 Intersil Corporation
 *
 */
//*****************************************************************************
//
//									I2C.c
//
//*****************************************************************************
//
//
#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "TW8835.h"

#include "I2C.h"
#include "printf.h"
#include "CPU.h"

/*
#define I2CD	P0
#define I2CD0	P0_0
#define I2CD1	P0_1
#define I2CD2	P0_2
#define I2CD3	P0_3
#define I2CD4	P0_4
#define I2CD5	P0_5
#define I2CD6	P0_6
#define I2CD7	P0_7
*/

DATA BYTE I2CD	_at_ 0x20;

#define I2CD0	00h
#define I2CD1	01h
#define I2CD2	02h
#define I2CD3	03h
#define I2CD4	04h
#define I2CD5	05h
#define I2CD6	06h
#define I2CD7	07h

//=============================================================================
//                                                                           
//=============================================================================
#if 1
void ddH(void)
{
	BYTE i;
	for ( i=0; i<30; i++ ) ;
}

//#define ddH0()

void I2CStartH()
{
	I2C_SDA = 1;	ddH();
	I2C_SCL = 1;	ddH();
	I2C_SDA = 0;	ddH();
	I2C_SCL = 0;
}

void I2CStopH()
{
	I2C_SDA = 0;	ddH();
	I2C_SCL = 1;	ddH();
	I2C_SDA = 1;
}

void I2CWriteDataH(BYTE value)
{
	I2CD = value;
#if 0
#pragma asm

;	clr EA

	clr	I2C_SCL
	mov	c, I2CD7
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

	clr	I2C_SCL
	mov	c, I2CD6
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

	clr	I2C_SCL
	mov	c, I2CD5
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

	clr	I2C_SCL
	mov	c, I2CD4
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

	clr	I2C_SCL
	mov	c, I2CD3
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

	clr	I2C_SCL
	mov	c, I2CD2
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

	clr	I2C_SCL
	mov	c, I2CD1
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

	clr	I2C_SCL
	mov	c, I2CD0
	mov I2C_SDA, c
	lcall ddH0	;;;
	setb I2C_SCL
	lcall ddH

;	setb EA

#pragma endasm
#else

    EA = 0;

    I2C_SCL=0;	I2C_SDA=(value & 0x80)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x40)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x20)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x10)? 1:0;	I2C_SCL=1;	ddH();

	I2C_SCL=0;	I2C_SDA=(value & 0x08)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x04)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x02)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x01)? 1:0;	I2C_SCL=1;	ddH();

	EA = 1;
#endif
	I2C_SCL=0;	ddH();
	I2C_SDA = 1;

	I2C_SCL=1;	ddH();
	I2C_SCL=0;
}

BYTE I2CReadDataH()
{   
    int i;
	BYTE value=0;
	I2C_SDA = 1;
#if 0
#pragma asm

;	clr		EA

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD7, c

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD6, c

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD5, c

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD4, c

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD3, c

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD2, c

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD1, c

	clr		I2C_SCL
	lcall	ddH
	setb	I2C_SCL
	lcall	ddH
	mov		c, I2C_SDA
	mov		I2CD0, c

;	setb	EA

#pragma endasm
#else

	EA = 0;
	
	I2C_SCL = 0;ddH();
	
	for(i=0; i<8; i++) {
		I2C_SCL = 1;ddH();
		value <<= 1;
		if(I2C_SDA) value |= 1;
		I2C_SCL = 0;ddH();
	}
	
	EA = 1;
	
#endif
	I2C_SCL=1;	ddH();
	I2C_SCL=0;

	I2CD = value;
	return I2CD;
}
//=============================================================================
//                                                                           
//=============================================================================
BYTE ReadI2C(BYTE addr, BYTE index)
{
//	BYTE val;

	if ( addr == 0 ) return (ReadTW88(index));
EA=0;
	I2CStartH();
	I2CWriteDataH(addr);
	I2CWriteDataH(index);
	I2CStartH();
	I2CWriteDataH(addr | 0x01);
	I2CReadDataH();
	I2CStopH();
EA=1;
	return I2CD;
}


void WriteI2C(BYTE addr, BYTE index, BYTE val)
{
	if ( addr == 0 ) {
		WriteTW88(index, val);
		return;
	}
EA=0;
	I2CStartH();
	I2CWriteDataH(addr);
	I2CWriteDataH(index);
	I2CWriteDataH(val);
	I2CStopH();
EA=1;
}
#endif
#if 0
void WriteI2CArray(BYTE addr, BYTE *RegSet)
{
	BYTE index, val;

	while (( RegSet[0] != 0xFF ) || ( RegSet[1]!= 0xFF )) {			// 0xff, 0xff is end of data
		index = *RegSet;
		val = *(RegSet+1);
		WriteI2C(addr, index, val);

		RegSet+=2;
	}
}
#endif
#if 0
//=============================================================================
//                                                                           
//=============================================================================
void I2CDeviceInitialize(BYTE *RegSet, BYTE delay)
{
	int	cnt=0;
	BYTE addr, index, val;

	addr = *RegSet;
	#ifdef DEBUG_TW88
	dPrintf("\nI2C address : %02bx", addr);
	#endif
	cnt = *(RegSet+1);
	RegSet+=2;

	while (( RegSet[0] != 0xFF ) || ( RegSet[1]!= 0xFF )) {			// 0xff, 0xff is end of data
		index = *RegSet;
		val = *(RegSet+1);
		WriteI2C(addr, index, val);

		if(delay)
			delay1ms(delay);
		//#ifdef DEBUG_TW88
		//dPrintf("\n    addr=%02x  index=%02x   val=%02x", (WORD)addr, (WORD)index, (WORD)val );
		//#endif

		RegSet+=2;
	}
}
#endif
void I2CWriteDataN(BYTE addr, BYTE index, BYTE *val, BYTE cnt)
{
	BYTE i;
	
    if ( addr == TW88I2CAddress ) {
		for ( i=0; i<cnt; i++) {
			WriteTW88(index, *val++);
			
			}
	return;
    }
#if 0		
	I2CStart();
	I2CWriteData(addr);
	I2CWriteData(index);

	for(i=0; i<cnt; i+=2){
		I2CWriteData(*(val+i));	
		dd();
	}
	I2CStop();
#endif	
}
#if 0
void I2CWriteDataN2(BYTE addr, BYTE index, BYTE *val, WORD cnt)
{
	WORD i;
	
    if ( addr == TW88I2CAddress ) {
		for ( i=0; i<cnt; i+=2) {
			WriteTW88(index, *val);
			val+=2;
			}
	return;
    }

#if 0		
	I2CStart();
	I2CWriteData(addr);
	I2CWriteData(index);

	for(i=0; i<cnt; i+=2){
		I2CWriteData(*(val+i));	
		dd();
	}
	I2CStop();
#endif	
}
#endif
#if 0
==============================OLD=================================

//*****************************************************************************
//
//									I2C.c
//
//*****************************************************************************
//
//
#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "I2C.h"
#include "printf.h"
#include "CPU.h"
#include "TW8835.h"
#include "OSD.h"

//=============================================================================
//                                                                           
//=============================================================================
BYTE ReadI2C(BYTE addr, BYTE index)
{
	BYTE val;
	BYTE i, j;

	if ( addr == 0 ) return (ReadTW88(index));

	j = ReadTW88( 0xff );
#ifdef MODEL_TW8835
	WriteTW88Page(PAGE4_SPI);
	i = ReadTW88(0xC1) & 0x10;
#else
	WriteTW88( 0xff, MCU_PAGE );
	i = ReadTW88( 0x20 ) & 4;	// is it cashe on?
#endif
	WriteTW88( 0xff, j );		// restore page

	if ( i ) {
		I2CStartH();
		I2CWriteDataH(addr);
		I2CWriteDataH(index);
		I2CStartH();
		I2CWriteDataH(addr | 0x01);
		val = I2CReadDataH();
		I2CStopH();
	}
	else {
		I2CStartL();
		I2CWriteDataL(addr);
		I2CWriteDataL(index);
		I2CStartL();
		I2CWriteDataL(addr | 0x01);
		val = I2CReadDataL();
		I2CStopL();
	}
	return val;
}


void WriteI2C(BYTE addr, BYTE index, BYTE val)
{
BYTE i, j;

	if ( addr == 0 ) {
		WriteTW88(index, val);
		return;
	}

	j = ReadTW88( 0xff );
#ifdef MODEL_TW8835
	WriteTW88Page(PAGE4_SPI);
	i = ReadTW88(0xC1) & 0x10;
#else
	WriteTW88( 0xff, MCU_PAGE );
	i = ReadTW88( 0x20 ) & 4;	// is it cashe on?
#endif
	WriteTW88( 0xff, j );		// restore page

	if ( i ) {
		I2CStartH();
		I2CWriteDataH(addr);
		I2CWriteDataH(index);
		I2CWriteDataH(val);
		I2CStopH();
	}
	else {
		I2CStartL();
		I2CWriteDataL(addr);
		I2CWriteDataL(index);
		I2CWriteDataL(val);
		I2CStopL();
	}
}

//=============================================================================
//                                                                           
//=============================================================================
/*
void dd(void)
{
	BYTE i, j;

	j = ReadTW88( 0xff );
	WriteTW88( 0xff, MCU_PAGE );
	if ( ReadTW88( 0x20 ) & 4 ) {		// is it cashe on?
	    i = ReadTW88( 0xff );
	}
	WriteTW88( 0xff, j );
}

void I2CStart()
{
	I2C_SDA = 1;	dd();
	I2C_SCL = 1;	dd();
	I2C_SDA = 0;	dd();
	I2C_SCL = 0;
}

void I2CStop()
{
	I2C_SDA = 0;	dd();
	I2C_SCL = 1;	dd();
	I2C_SDA = 1;
}

void I2CWriteData(BYTE value)
{
	I2C_SCL=0;	I2C_SDA=(value & 0x80)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x40)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x20)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x10)? 1:0;	I2C_SCL=1;	dd();

	I2C_SCL=0;	I2C_SDA=(value & 0x08)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x04)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x02)? 1:0;	I2C_SCL=1;	dd();
	I2C_SCL=0;	I2C_SDA=(value & 0x01)? 1:0;	I2C_SCL=1;	dd();


	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	//	I2Cdelay();
	I2C_SDA = 1;	//	I2Cdelay();

	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	//	I2Cdelay();
	dd();
	I2C_SCL = 0;
}

BYTE I2CReadData()
{
//	BYTE i;
	BYTE value;

	I2C_SDA = 1;
	I2C_SCL = 0;    dd();

//	
//	for(i=0; i<8; i++) {
//		I2C_SCL = 1;
//		value <<= 1;
//		//if(I2C_SDA) value |= 1;
//		value |= I2C_SDA;
//		dd();
//		I2C_SCL = 0;
//		dd();
//	}
//	
	I2C_SCL = 1;    dd();
	value = I2C_SDA;					  				// bit 7
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA;									// bit 6
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 5
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA;									// bit 4
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA;  									// bit 3
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 2
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 1
	I2C_SCL = 0;    dd();  	I2C_SCL = 1;    dd();
	value <<= 1;
	value |= I2C_SDA; 									// bit 0

	I2C_SCL = 1;	// HHY 3.00
	dd();
	I2C_SCL = 0;

	return value;

}
*/
void I2CStartL()
{
	I2C_SDA = 1;
	I2C_SCL = 1;
	I2C_SDA = 0;
	I2C_SCL = 0;
}

void I2CStopL()
{
	I2C_SDA = 0;
	I2C_SCL = 1;
	I2C_SDA = 1;
}

void I2CWriteDataL(BYTE value)
{
	I2C_SCL=0;	I2C_SDA=(value & 0x80)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x40)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x20)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x10)? 1:0;	I2C_SCL=1;	I2C_SCL=1;

	I2C_SCL=0;	I2C_SDA=(value & 0x08)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x04)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x02)? 1:0;	I2C_SCL=1;	I2C_SCL=1;
	I2C_SCL=0;	I2C_SDA=(value & 0x01)? 1:0;	I2C_SCL=1;	I2C_SCL=1;


	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	//	I2Cdelay();
	I2C_SDA = 1;	//	I2Cdelay();

	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	//	I2Cdelay();

	I2C_SCL = 0;
}

BYTE I2CReadDataL()
{
	BYTE value;

	I2C_SDA = 1;
	
	I2C_SCL = 0;	I2C_SCL = 1;	value = I2C_SDA;	
	I2C_SCL = 0;  	I2C_SCL = 1;	value <<= 1;  	value |= I2C_SDA;	
	I2C_SCL = 0;  	I2C_SCL = 1;	value <<= 1;	value |= I2C_SDA;
	I2C_SCL = 0;  	I2C_SCL = 1;	value <<= 1;	value |= I2C_SDA;
	I2C_SCL = 0;  	I2C_SCL = 1;	value <<= 1;	value |= I2C_SDA;
	I2C_SCL = 0;  	I2C_SCL = 1;	value <<= 1;	value |= I2C_SDA;
	I2C_SCL = 0;  	I2C_SCL = 1;	value <<= 1;	value |= I2C_SDA;
	I2C_SCL = 0;  	I2C_SCL = 1;	value <<= 1;	value |= I2C_SDA;

	I2C_SCL = 1;
	I2C_SCL = 0;

	return value;
}

void ddH(void)
{
	BYTE i;

	for ( i=0; i<5; i++ ) ;
}

void I2CStartH()
{
	I2C_SDA = 1;	ddH();
	I2C_SCL = 1;	ddH();
	I2C_SDA = 0;	ddH();
	I2C_SCL = 0;
}

void I2CStopH()
{
	I2C_SDA = 0;	ddH();
	I2C_SCL = 1;	ddH();
	I2C_SDA = 1;
}

void I2CWriteDataH(BYTE value)
{
	I2C_SCL=0;	I2C_SDA=(value & 0x80)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x40)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x20)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x10)? 1:0;	I2C_SCL=1;	ddH();

	I2C_SCL=0;	I2C_SDA=(value & 0x08)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x04)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x02)? 1:0;	I2C_SCL=1;	ddH();
	I2C_SCL=0;	I2C_SDA=(value & 0x01)? 1:0;	I2C_SCL=1;	ddH();


	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	// HHY 3.00
	I2C_SCL = 0;	//	I2Cdelay();
	I2C_SDA = 1;	//	I2Cdelay();

	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	// HHY 3.00
	I2C_SCL = 1;	//	I2Cdelay();
	ddH();
	I2C_SCL = 0;
}

BYTE I2CReadDataH()
{
	BYTE value;

	I2C_SDA = 1;
	
	I2C_SCL = 0;    ddH();	I2C_SCL = 1;    ddH();	value = I2C_SDA;				
	I2C_SCL = 0;    ddH();  I2C_SCL = 1;    ddH();	value = (value<<1) | I2C_SDA;	
	I2C_SCL = 0;    ddH();  I2C_SCL = 1;    ddH();	value = (value<<1) | I2C_SDA;	
	I2C_SCL = 0;    ddH();	I2C_SCL = 1;    ddH();	value = (value<<1) | I2C_SDA;	
	I2C_SCL = 0;    ddH();  I2C_SCL = 1;    ddH();	value = (value<<1) | I2C_SDA;	
	I2C_SCL = 0;    ddH();  I2C_SCL = 1;    ddH();	value = (value<<1) | I2C_SDA;	
	I2C_SCL = 0;    ddH();  I2C_SCL = 1;    ddH();	value = (value<<1) | I2C_SDA;	
	I2C_SCL = 0;    ddH();  I2C_SCL = 1;    ddH();	value = (value<<1) | I2C_SDA;

	I2C_SCL = 1;	ddH();
	I2C_SCL = 0;

	return value;
}
//=============================================================================
//                                                                           
//=============================================================================
//addr	cnt
//index value
//......
//0xff, 0xff  - end of data

void I2CDeviceInitialize(BYTE *RegSet)
{
	int	cnt=0;
	BYTE addr, index, val;

	addr = *RegSet;
	#ifdef DEBUG_TW88
	dPrintf("\nI2C address : %02bx", addr);
	#endif
	cnt = *(RegSet+1);
	RegSet+=2;

//	OsdWaitVBlank(1);

	while (( RegSet[0] != 0xFF ) || ( RegSet[1]!= 0xFF )) {			// 0xff, 0xff is end of data
		index = *RegSet;
		val = *(RegSet+1);
		WriteI2C(addr, index, val);

		#ifdef DEBUG_TW88
		dPrintf("\n    addr=%02x  index=%02x   val=%02x", (WORD)addr, (WORD)index, (WORD)val );
		#endif

		RegSet+=2;
	}

	//WriteTW88(0xff, 0x00);		// set page 0
}
#endif
